grammar Pie;

program : ( functionDefinition | statement )+ EOF 
	;

//expr
atom 
	:	INT		    
	|	CHAR	    
	|	FLOAT	    
	|	STRING	    
	|	qid		    
	|	call
	|	instance
	|	'(' expr ')'
	;

mulexpr 
	:	atom ('*' atom)*
	;

addexpr
	:	mulexpr ('+' mulexpr)*  #addExpr
    | mulexpr ('-' mulexpr)*    #subExpr
	;

expr:	addexpr ('==' addexpr)?  #eqExpr
    | addexpr ('<' addexpr)?     #ltExpr
    ;

// statement
statement
	:	structDefinition         #structDefStatement
	|	qid '=' expr NL	         #assignStatement	
	|	'return' expr NL  		 #returnStatement
	|	'print' expr NL	 		 #printStatement
	|	'if' expr slist ('else' slist)? #ifStatement
	|	'while' expr slist        #whileStatement		
	|	call NL					  #callStatement
	|	NL					      #emptyStatement
	;

slist
	:	':' NL statement+ '.' NL
	|	statement
    ;

// struct
structDefinition
    :   'struct' ID '{' 
		    vardef (',' vardef)* 
        '}' 
        NL
    ;
vardef: ID;

instance:	'new' ID;

qid : ID             #simpleVar
    | ID ('.' ID)+   #fieldVar
    ;

//func
functionDefinition
	:	'def' ID '(' (vardef (',' vardef)* )? ')'
		    slist
	;
				
call :	ID '(' (expr (',' expr )*)? ')';


//Lexer
INT :   '0'..'9'+ ;
    
FLOAT
	:	INT '.' INT*
	|	'.' INT+
	;
CHAR:	'\'' . '\'' ;

STRING:	'"' .+ '"' ;

fragment
LETTER
	:   ('a'..'z' | 'A'..'Z')
    ;
ID  :   LETTER (LETTER | '0'..'9')*  ;

NL	:	'\r'? '\n' ;

WS  :   (' '|'\t') -> skip ;

SL_COMMENT :   '#' ~('\r'|'\n')* -> skip ;